<script setup>
import {
  ref,
  reactive,
  onMounted,
  onActivated,
  nextTick,
  getCurrentInstance,
  toRefs,
  watch,
  onDeactivated,
  inject,
  provide
} from 'vue'

import Message from './Message.vue'
import InputBox from './InputBox.vue'
import { isIos } from '../../../utils/host'
import { useCommonCheckbox } from '../../../hooks/mobile'
import { getDict } from '../../../service/api'

import AudioPlayer from '../../../utils/audioplayer'
import { useAudioStore } from '../../../stores/audio'

const { appContext } = getCurrentInstance()
const proxy = appContext.config.globalProperties
const config = proxy.$config

const Emit = defineEmits(['doAction', 'playVoice']) // 触发父组件调用数字人动作函数

const animateScale = inject('animateScale')

const props = defineProps({
  muted: {
    type: Boolean
  },
  sessionId: {
    type: String,
    default: ''
  },
  lan: {
    type: String,
    default: ''
  }
})

const { muted, sessionId, lan } = toRefs(props)

const initPlayer = () => {
  window.player = new AudioPlayer(false, () => {
    isAnswering.value = false
    canClickModel.value = true
    Emit('doAction', 'standby')
  })
  if (window.player) {
    window.player.setMuted(muted.value)
  }
}

const handleClick = () => {
  initPlayer()
  document.removeEventListener('click', handleClick)
}
document.addEventListener('click', handleClick)

watch(muted, (v) => {
  if (!isIos()) {
    window.player.setMuted(v)
  }
})

// mp3播放完毕
const voiceEnd = () => {
  console.log('voiceEnd事件')
  isAnswering.value = false
  canClickModel.value = true
  playVoiceAndAnimate('Standby')
}

// 定时器
const timer1 = ref(null) // 控制mp3播放
const timer2 = ref(null) // 控制动画播放
let firstTime = true // 第一次播放语音
// 播放mp3或者客户端播放音频、以及数字人动作
const playVoiceAndAnimate = (type) => {
  clearTimeout(timer1.value)
  clearTimeout(timer2.value)
  canClickModel.value = false
  if (
    (type === 'NoAnswer1' && config.apologyVoice) ||
    (type === 'NoAnswer2' && config.apologyHintSecondVoice) ||
    (type === 'NoAnswer3' && config.apologyHintThreeVoice)
  ) {
    Emit('doAction', 'speak')
    Emit('playVoice', type)
  } else if (type === 'Hello' && config.welcomeVoice) {
    Emit('doAction', 'welcome')
    timer2.value = setTimeout(() => {
      Emit('doAction', 'speak')
    }, 3450)
    timer1.value = setTimeout(() => {
      Emit('playVoice', 'Welcome')
    }, 200)
  } else if (type === 'Standby') {
    canClickModel.value = true
    Emit('doAction', 'standby')
  } else if (type === 'OneAnswer') {
    const time = firstTime ? 1000 : 0
    firstTime = false
    timer2.value = setTimeout(() => {
      Emit('doAction', 'speak')
    }, time)
  }
}

const audioStore = useAudioStore()
const stopVoiceAndAnimate = () => {
  audioStore.setPlaying('')
  clearTimeout(timer1.value)
  clearTimeout(timer2.value)
  canClickModel.value = true
  stopAi()
}

// 是否能点击身体说话并动作
const canClickModel = ref(true)
const clickBodyVoiceAndAnimate = () => {
  if (canClickModel.value) {
    playVoiceAndAnimate('Hello')
  }
}

// 对话配置信息
const dialogSettings = reactive({
  serviceModel: '',
  datasetFlag: 1,
  networkFlag: 0
})
const changeSetting = (key, value) => {
  dialogSettings[key] = value
}

const model = ref('')
const changeModel = (value) => {
  model.value = value
}

const tags = ref(['答非所问', '太简单', '太复杂', '看不懂', '其他'])
const changeFeedType = (item) => {
  feedType.value = item
}
const defaultFeedType = ref('答非所问')
const getDictData = async () => {
  const data = await getDict('evaluateType')
  if (data.length > 0) {
    tags.value = data.map((tag) => tag.dictValue)
    defaultFeedType.value = data[0].dictValue
  }
}

const {
  isZDWX,
  docObj,
  chatBox,
  messages,
  isAnswering,
  isPending,
  send,
  sendInput,
  scroll,
  fixScroll,
  testTransportStatus,
  checkShowKefu,
  showRef,
  showRefPop,
  showEvalute,
  evaluteValue,
  showEvalutePop,
  feedType,
  evalute,
  changeOpsStatus,
  refContent,
  showImgPreview,
  stopAi,
  pushAgent,
  autoScroll
} = useCommonCheckbox(
  proxy,
  sessionId,
  playVoiceAndAnimate,
  stopVoiceAndAnimate,
  Emit,
  animateScale,
  model,
  dialogSettings,
  defaultFeedType
)

// 初始化前置检测
if (config.needCheckTransportStatus) {
  testTransportStatus()
}

// 新建消息  或 展示历史消息
const showMessages = (msgs) => {
  if (msgs) {
    messages.value = msgs
  } else {
    messages.value = []
    pushAgent('XYWD')
  }
  scroll()
}

// messages暴露给父组件
defineExpose({
  messages,
  voiceEnd,
  send,
  clickBodyVoiceAndAnimate,
  stopVoiceAndAnimate,
  showMessages,
  initPlayer
})

const newMsg = (msg) => {
  if (!window.player && !isIos()) {
    initPlayer()
  }
  sendInput(msg)
}

const iosPlayVoice = (type) => {
  Emit('playVoice', '')
  setTimeout(() => {
    Emit('doAction', 'speak')
  }, 25)
}

const iosPauseVoice = () => {
  playVoiceAndAnimate('Standby')
}

const iosEndVoice = () => {
  playVoiceAndAnimate('Standby')
}

const setDoc = (e) => {
  isZDWX.value = true
  docObj.value.id = e.id
  docObj.value.name = e.name
}
const clearDoc = () => {
  isZDWX.value = false
  docObj.value.id = null
  docObj.value.name = ''
}

// 监听手机键盘是否弹起落下
const keyBoardStatus = ref('down')
if (/Android/gi.test(navigator.userAgent)) {
  const innerHeight = window.innerHeight
  window.addEventListener('resize', () => {
    const newInnerHeight = window.innerHeight
    if (innerHeight > newInnerHeight) {
      // 键盘弹出事件处理
      setTimeout(() => {
        keyBoardStatus.value = 'up'
        scroll()
      }, 100)
    } else {
      // 键盘收起事件处理
      setTimeout(() => {
        keyBoardStatus.value = 'down'
        scroll()
      }, 100)
    }
  })
} else {
  window.addEventListener('focusin', (e) => {
    if (e.target.getAttribute('id') !== 'message-input') return
    // 键盘弹出事件处理
    setTimeout(() => {
      keyBoardStatus.value = 'up'
      scroll()
    }, 100)
  })
  window.addEventListener('focusout', () => {
    // 键盘收起事件处理
    setTimeout(() => {
      keyBoardStatus.value = 'down'
      scroll()
    }, 100) // 100ms延时 是为了避免点击发送按钮时首先触发 focusout，然后发送按钮就直接消失的问题
  })
}

const agentType = ref(1)
const setAgentType = (type) => {
  agentType.value = type
}
provide('agentType', agentType)
provide('setAgentType', setAgentType)

// 页面挂载钩子
onMounted(() => {
  nextTick(() => {
    chatBox.value.addEventListener('scroll', fixScroll)
    chatBox.value.addEventListener('touchstart', () => {
      if (isAnswering.value) {
        autoScroll.value = false
      }
    })
    pushAgent('XYWD')
    getDictData()
  })
})
// 页面激活钩子
onActivated(() => {
  scroll()
})

onDeactivated(() => {
  stopVoiceAndAnimate()
})
</script>

<template>
  <div class="chat-component">
    <div
      class="chat-wrap"
      :class="{ keyboartstatus_up: keyBoardStatus === 'up' && agentType !== 2 }"
    >
      <div class="chat-box" ref="chatBox">
        <Message
          v-for="(item, index) in messages"
          :key="index"
          :i="index"
          v-bind="item"
          :is-answering="isAnswering"
          :muted="muted"
          :total="messages.length"
          @emit-send="send"
          @emit-scroll="scroll"
          @emit-kefu="checkShowKefu(1)"
          @emit-ref="showRef"
          @emit-img="showImgPreview"
          @stop-ai="stopVoiceAndAnimate"
          @emit-evalute="showEvalute"
          @emit-status="changeOpsStatus"
          @emit-play="iosPlayVoice"
          @emit-pause="iosPauseVoice"
          @emit-end="iosEndVoice"
          @emit-doc="setDoc"
        />
      </div>
    </div>
    <InputBox
      :lan="lan"
      :doc="docObj"
      :is-answering="isAnswering"
      :is-Pending="isPending"
      @send-input="newMsg"
      @stop-ai="stopVoiceAndAnimate"
      @clear-doc="clearDoc"
      @push-agent="pushAgent"
      @change-setting="changeSetting"
      @change-model="changeModel"
    />
    <van-popup
      id="refpop"
      :show="showRefPop"
      closeable=""
      position="bottom"
      @click-overlay="showRefPop = false"
      @click-close-icon="showRefPop = false"
    >
      <div class="info" id="refpopInfo" v-html="refContent" />
    </van-popup>
    <van-popup
      id="evalutepop"
      :show="showEvalutePop"
      closeable=""
      @click-overlay="showEvalutePop = false"
      @click-close-icon="showEvalutePop = false"
    >
      <div class="form">
        <div class="tags">
          <div
            class="tag"
            :class="{ active: item === feedType }"
            v-for="(item, index) in tags"
            :key="index"
            @click="changeFeedType(item)"
          >
            {{ item }}
          </div>
        </div>
        <div class="item">
          <span
            ><span style="color: #ff0000">* </span
            >请详述问题，向老师请求帮助</span
          >
          <input type="text" v-model="evaluteValue" />
        </div>
      </div>
      <div class="btn" @click="evalute">确定</div>
    </van-popup>
  </div>
</template>

<style lang="less">
.small .chat-component .chat-wrap {
  height: calc(100% - 2.3rem);
}
.small .chat-component .chat-wrap.keyboartstatus_up {
  height: calc(100% - 2.3rem);
}
.chat-component {
  width: 100%;
  height: 100%;
  .chat-wrap {
    width: 100%;
    height: calc(100% - 2.5rem);
    background-color: transparent;
    overflow: hidden;
    position: relative;
    .chat-box {
      width: 100%;
      height: 100%;
      background-color: transparent;
      overflow-y: auto;
      position: absolute;
      left: 0;
      top: 0;
      .van-loading__spinner {
        display: none;
      }
      .van-loading__text,
      .van-pull-refresh__text {
        width: 150px;
        height: 20px;
        line-height: 20px;
        background: #eaf9fd;
        border-radius: 16px;
        font-size: 14px;
        color: #4792e4;
      }
      .van-pull-refresh__text {
        margin: 0 auto;
      }
    }
  }
}
</style>
